﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;

namespace NetLogger
{
	public class NetErrorLog
	{
		public const string LogFileName = "NetManagerLog.txt";

		private LinkedList<string> _formatStrings;
		private LinkedList<object[]> _args;
		private LinkedList<DateTimeOffset> _times;
		private EventWaitHandle _newLog;
		private EventWaitHandle _terminate;

		public NetErrorLog( EventWaitHandle terminate )
		{
			_formatStrings = new LinkedList<string>();
			_args = new LinkedList<object[]>();
			_times = new LinkedList<DateTimeOffset>();
			_newLog = new EventWaitHandle( false, EventResetMode.AutoReset );
			_terminate = terminate;

			ThreadPool.QueueUserWorkItem( new WaitCallback( WriteLogEntries ) );
		}

		public void Write( string format, params object[] args )
		{
			DateTimeOffset
				now = DateTimeOffset.Now;

			lock ( _formatStrings )
			{
				_formatStrings.AddLast( format );
				_args.AddLast( args );
				_times.AddLast( now );
			}

			_newLog.Set();
		}

		private void WriteLogEntries( object state )
		{
			string
				fileName;
			string[]
				formatStrings;
			object[][]
				args;
			DateTimeOffset[]
				times;
			WaitHandle[]
				handles = new WaitHandle[] { _terminate, _newLog };
			int
				handleIndex;

			fileName = Environment.GetFolderPath( Environment.SpecialFolder.MyDocuments ) + Path.DirectorySeparatorChar + LogFileName;

			using ( StreamWriter writer = File.AppendText( fileName ) )
			{
				do
				{
					handleIndex = WaitHandle.WaitAny( handles );
					if ( handleIndex == 1 )
					{
						lock ( _formatStrings )
						{
							formatStrings = _formatStrings.ToArray();
							args = _args.ToArray();
							times = _times.ToArray();
							_formatStrings.Clear();
							_args.Clear();
							_times.Clear();
						}

						for ( int i = 0; i < formatStrings.Length; i++ )
						{
							writer.WriteLine( "Date: {0}", times[ i ] );
							writer.WriteLine( formatStrings[ i ], args[ i ] );
							writer.WriteLine( "--------------------------------------------------" );
						}
					}
				} while ( handleIndex > 0 );
			}
		}
	}
}
